Good prompts make Stagehand reliable. Bad prompts cause failures. Here’s how to write prompts that work consistently.
Act Method
Use act()
for single actions on web pages. Each action should be focused and clear.
// Good - Single, specific actions
await page.act("click the 'Add to Cart' button");
await page.act("type 'user@example.com' into the email field");
// Bad - Multiple actions combined
await page.act("fill out the form and submit it");
await page.act("login with credentials and navigate to dashboard");
Use Element Types, Not Colors
Describe elements by their type and function rather than visual attributes like color.
// Good - Element types and descriptive text
await page.act("click the 'Sign In' button");
await page.act("type into the email input field");
// Bad - Color-based descriptions
await page.act("click the blue button");
await page.act("type into the white input");
Use Descriptive Language
// Good - Clear element identification
await page.act("click the 'Next' button at the bottom of the form");
await page.act("type into the search bar at the top of the page");
// Bad - Vague descriptions
await page.act("click next");
await page.act("type into search");
Choose the Right Action Verbs
- Click for buttons, links, checkboxes
- Type for text inputs
- Select for dropdowns
- Check/uncheck for checkboxes
- Upload for file inputs
// Good
await page.act("click the submit button");
await page.act("select 'Option 1' from dropdown");
// Bad
await page.act("click submit");
await page.act("choose option 1");
Protect Sensitive Data
Variables keep sensitive information out of prompts and logs.
// Good - Secure approach
await page.act({
action: "enter %username% in the email field",
variables: {
username: "user@example.com"
}
});
await page.act({
action: "enter %password% in the password field",
variables: {
password: process.env.USER_PASSWORD
}
});
// Bad - Insecure approach
await page.act("type 'mySecretPassword123' into the password field");
Set verbose: 0
in your Stagehand config to prevent secrets from appearing in logs.
Use extract()
to pull structured data from pages. Define clear schemas and provide context.
Schema Best Practices
Use descriptive field names, correct types, and detailed descriptions. Field descriptions provide context that helps the agent understand exactly what to extract.
// Good - Descriptive names, correct types, and helpful descriptions
const productData = await page.extract({
instruction: "Extract product information",
schema: z.object({
productTitle: z.string().describe("The main product name displayed on the page"),
priceInDollars: z.number().describe("Current selling price as a number, without currency symbol"),
isInStock: z.boolean().describe("Whether the product is available for purchase")
})
});
// Bad - Generic names, wrong types, no descriptions
const data = await page.extract({
instruction: "Get product details",
schema: z.object({
name: z.string(), // Too generic, no context
price: z.string(), // Should be number
stock: z.string() // Should be boolean, no context
})
});
Handle Arrays Correctly
Always wrap schemas in objects for reliable extraction.
// Good - Array wrapped in object
const listings = await page.extract({
instruction: "Extract all apartment listings",
schema: z.object({
apartments: z.array(z.object({
address: z.string(),
rent: z.number()
}))
})
});
// Bad - Bare array
const listings = await page.extract({
instruction: "Extract apartment listings",
schema: z.array(z.string()) // Don't do this
});
Use Proper URL Types
Specify URL types to tell Stagehand to extract URLs. Without proper URL types, Stagehand won’t extract URLs.
// Good - Tells Stagehand to extract URLs
const links = await page.extract({
instruction: "Extract navigation links",
schema: z.object({
links: z.array(z.object({
text: z.string(),
url: z.string().url() // Required for URL extraction
}))
})
});
Observe Method
Use observe()
to discover actionable elements before acting on them.
Check Elements First
Verify elements exist before taking action to avoid errors.
// Check for elements first
const loginButtons = await page.observe("Find the login button");
if (loginButtons.length > 0) {
await page.act(loginButtons[0]);
} else {
console.log("No login button found");
}
Be Specific About Element Types
// Good - Specific element types
const submitButtons = await page.observe("Find submit button in the form");
const dropdowns = await page.observe("Find the state dropdown menu");
// Bad - Too vague
const elements = await page.observe("Find submit stuff");
const things = await page.observe("Find state selection");
Agent Method
Use agent()
for complex, multi-step workflows. Provide detailed instructions and set appropriate limits.
Navigate First
Don’t include navigation in agent tasks. Handle it separately.
// Good - Navigate first
await page.goto('https://amazon.com');
await agent.execute('Search for wireless headphones under $100 and add the best rated one to cart');
// Bad - Navigation in task
await agent.execute('Go to Amazon, search for headphones, and add one to cart');
Be Highly Specific
Detailed instructions lead to better results.
// Good - Detailed instructions
await agent.execute({
instruction: "Find Italian restaurants in Brooklyn that are open after 10pm, have outdoor seating, and are rated 4+ stars. Save the top 3 results.",
maxSteps: 25
});
// Bad - Vague instructions
await agent.execute("Find some good restaurants");
Set Appropriate Step Limits
Match step limits to task complexity.
// Simple task - fewer steps
await agent.execute({
instruction: "Subscribe to the newsletter with email 'user@example.com'",
maxSteps: 10
});
// Complex task - more steps
await agent.execute({
instruction: "Research and compare 5 project management tools with pricing and features",
maxSteps: 50
});
Include Success Criteria
Tell the agent how to know when it’s done.
// Good - Clear success criteria
await agent.execute({
instruction: "Add 3 smartphone cases to cart and confirm the cart shows exactly 3 items with total price",
maxSteps: 20
});
// Bad - No validation
await agent.execute("Add some items to cart");
Common Mistakes to Avoid
- Combining multiple actions - Keep each
act()
call to one action
- Using vague descriptions - Be specific about which elements to interact with
- Exposing sensitive data - Always use variables for credentials
- Skipping validation - Check results before proceeding
Testing Your Prompts
- Start simple - Test basic functionality first
- Add complexity gradually - Build up to complex workflows
- Monitor results - Use logging to understand what’s happening
- Iterate based on failures - Refine prompts when they don’t work
Remember: Good prompting is iterative. When in doubt, be more specific rather than less.